using System;
using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Logic;
using LFloatMath.Math;

namespace IQIGame.Onigao.GamePlay
{
    public class AttributeProperty
    {
        public int lv;
        private int[] mBaseProperty = new int[(int)EAttributeType.Max];
        private int[] mPercentProperty = new int[(int)EAttributeType.Max];
        private int[] mAddProperty = new int[(int)EAttributeType.Max];

        private LFloat[] mOutProperty = new LFloat[(int)EAttributeType.Max];

        public static Dictionary<EAttributeType, EAttributeType> maxValue;

        static AttributeProperty()
        {
            maxValue = new Dictionary<EAttributeType, EAttributeType>();
            maxValue[EAttributeType.MaxHp] = EAttributeType.Hp;
            maxValue[EAttributeType.MaxSP] = EAttributeType.SP;
        }

        public LFloat Get(EAttributeType rType)
        {
            return this.mOutProperty[(int)rType];
        }

        /// <summary>
        /// (面板，百分比，加)
        /// </summary>
        /// <param name="rType"></param>
        /// <returns></returns>
        public (int, int, int) GetAll(EAttributeType rType)
        {
            var nIndex = (int)rType;
            return (this.mBaseProperty[nIndex], this.mPercentProperty[nIndex], this.mAddProperty[nIndex]);
        }

        public LFloat Set(EAttributeType rType, int nValue, EAttributeAddType rAddType = EAttributeAddType.Base)
        {
            var nIndex = (int)rType;

            int[] rArr = this.mBaseProperty;
            switch (rAddType)
            {
                case EAttributeAddType.Percent:
                    rArr = this.mPercentProperty;
                    break;
                case EAttributeAddType.Add:
                    rArr = this.mAddProperty;
                    break;
            }
            if (nIndex < 0 || nIndex >= (int)EAttributeType.Max)
            {
                LogGame.LogError("属性越界" + nIndex);
                return default;
            }
            if (rAddType == EAttributeAddType.Base && rType == EAttributeType.MaxHp)
            {
                nValue = Math.Max(nValue, 1);
            }
            rArr[nIndex] = nValue;
            return this.Refresh(nIndex);
        }

        public LFloat Add(EAttributeType rType, int nValue)
        {
            var nIndex = (int)rType;
            if (nIndex < 0 || nIndex >= (int)EAttributeType.Max)
            {
                LogGame.LogError("属性越界" + nIndex);
                return default;
            }
            this.mAddProperty[nIndex] += nValue;
            return this.Refresh(nIndex);
        }

        public LFloat AddPercent(EAttributeType rType, int nValue)
        {
            var nIndex = (int)rType;
            this.mPercentProperty[nIndex] += nValue;
            if (nIndex < 0 || nIndex >= (int)EAttributeType.Max)
            {
                LogGame.LogError("属性越界" + nIndex);
                return default;
            }
            return this.Refresh(nIndex);
        }

        private LFloat Refresh(int nIndex)
        {
            var nValue = this.mBaseProperty[nIndex] * (LFloat.Precision + this.mPercentProperty[nIndex]) * Formula_Attr.FLT_00001
                         + this.mAddProperty[nIndex];
            var rAttrConfig = TableCenter.attribute.Get(nIndex);
            if (rAttrConfig == null)
            {
                return LFloat.zero;
            }
            var nMin = rAttrConfig.Min.ToLFloat();
            var nMax = rAttrConfig.Max.ToLFloat();
            nValue = LMath.Clamp(nValue, nMin, nMax);

            // 不可超过最大值
            var rType = (EAttributeType)nIndex;
            if (maxValue.TryGetValue(rType, out var rValueType))
            {
                this.mAddProperty[(int)rValueType] = LMath.Clamp(this.mAddProperty[(int)rValueType].ToLFloat(), LFloat.zero, nValue).ToInt();
                this.Refresh((int)rValueType);
            }
            return this.mOutProperty[nIndex] = nValue;
        }

        public void Initialize(int[] attrValue, int lv)
        {
            this.Clear();
            this.lv = lv;
            var nLen = Math.Min(attrValue.Length, (int)EAttributeType.Max);
            for (int i = (int)EAttributeType.Min + 1; i < nLen; i++)
            {
                var rAttrType = (EAttributeType)i;
                if (rAttrType == EAttributeType.Hp || rAttrType == EAttributeType.SP)
                {
                    this.Add(rAttrType, attrValue[i]);
                }
                else
                {
                    this.Set(rAttrType, attrValue[i]);
                }
            }
        }

        public void Initialize(IReadOnlyList<int> rAttr, int lv)
        {
            this.Clear();
            this.lv = lv;
            var nLen = (int)EAttributeType.Max;
            for (int i = (int)EAttributeType.Min + 1; i < nLen; i++)
            {
                var rAttrType = (EAttributeType)i;
                if (rAttrType == EAttributeType.Hp || rAttrType == EAttributeType.SP)
                {
                    this.Add(rAttrType, rAttr[i]);
                }
                else
                {
                    this.Set(rAttrType, rAttr[i]);
                }
            }
        }

        private void Clear()
        {
            this.lv = 0;
            for (int i = 0; i < this.mAddProperty.Length; i++)
            {
                this.mAddProperty[i] = 0;
            }
            for (int i = 0; i < this.mPercentProperty.Length; i++)
            {
                this.mPercentProperty[i] = 0;
            }
        }
    }

    public enum EAttributeAddType
    {
        Base,
        Percent,
        Add,
    }
}